package cn.dagteam.springboot.mongodb.starter.repository.support;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.springframework.util.StringUtils;

import cn.dagteam.springboot.mongodb.starter.Constants;
import lombok.Data;

/**
 * @author gaofeng
 */
@Data
public class QueryFilter implements Serializable {
	
	private static final long serialVersionUID = Constants.VERSION;
	
	private String fieldName;
	
	private Operator op;
	
	private Object value;
	
	public QueryFilter(String fieldName, Operator op, Object value) {
		super();
		this.fieldName = fieldName;
		this.op = op;
		this.value = value;
	}

	public QueryFilter() {
		super();
	}
	
	public static  QueryFilterBuilder builder() {
		return new QueryFilterBuilder();
	}

	public static class QueryFilterBuilder {
		
		private List<QueryFilter> filters = new ArrayList<>();
		
		public List<QueryFilter> build() {
			return this.filters;
		}
		
		public QueryFilterBuilder add(String fieldName, Operator op, Object value) {
			filters.add(new QueryFilter(fieldName, op, value));
			return this;
		}
		
		public QueryFilterBuilder eq(String fieldName, Object value) {
			filters.add(new QueryFilter(fieldName, Operator.EQ, value));
			return this;
		}
		
		public QueryFilterBuilder neq(String fieldName, Object value) {
			filters.add(new QueryFilter(fieldName, Operator.NEQ, value));
			return this;
		}
		
		public QueryFilterBuilder like(String fieldName, Object value) {
			filters.add(new QueryFilter(fieldName, Operator.LIKE, value));
			return this;
		}
		
		public QueryFilterBuilder llike(String fieldName, Object value) {
			filters.add(new QueryFilter(fieldName, Operator.LLIKE, value));
			return this;
		}
		
		public QueryFilterBuilder rlike(String fieldName, Object value) {
			filters.add(new QueryFilter(fieldName, Operator.RLIKE, value));
			return this;
		}
		
		public QueryFilterBuilder gt(String fieldName, Object value) {
			filters.add(new QueryFilter(fieldName, Operator.GT, value));
			return this;
		}
		
		public QueryFilterBuilder lt(String fieldName, Object value) {
			filters.add(new QueryFilter(fieldName, Operator.LT, value));
			return this;
		}
		
		public QueryFilterBuilder gte(String fieldName, Object value) {
			filters.add(new QueryFilter(fieldName, Operator.GTE, value));
			return this;
		}
		
		public QueryFilterBuilder lte(String fieldName, Object value) {
			filters.add(new QueryFilter(fieldName, Operator.LTE, value));
			return this;
		}
		
		public QueryFilterBuilder in(String fieldName, Object... value) {
			filters.add(new QueryFilter(fieldName, Operator.IN, value));
			return this;
		}
		
		public QueryFilterBuilder in(String fieldName, Collection<?> value) {
			filters.add(new QueryFilter(fieldName, Operator.IN, value));
			return this;
		}
		
		public QueryFilterBuilder nin(String fieldName, Object... value) {
			filters.add(new QueryFilter(fieldName, Operator.NOTIN, value));
			return this;
		}
		
		public QueryFilterBuilder nin(String fieldName, Collection<?> value) {
			filters.add(new QueryFilter(fieldName, Operator.NOTIN, value));
			return this;
		}
		
		public QueryFilterBuilder EXISTS(String fieldName) {
			filters.add(new QueryFilter(fieldName, Operator.EXISTS, "true"));
			return this;
		}
		
		public QueryFilterBuilder NEXISTS(String fieldName) {
			filters.add(new QueryFilter(fieldName, Operator.NEXISTS, "false"));
			return this;
		}
		
		public QueryFilterBuilder parse(Map<String, ?> filterMap) {
			filterMap.entrySet().parallelStream().forEach(entry -> {
				String key = entry.getKey();
				Object value = entry.getValue();
				// 查询内容是空的，直接跳过查询条件
				if (value == null || !StringUtils.hasText(value.toString())) {
					return;
				}
				// 默认给等于的判断
				Operator op = Operator.EQ;
				String fieldName = key;
				if (key.indexOf("_") != -1) {
					try {
						op = Operator.valueOf(key.substring(0, key.indexOf("_")));
						fieldName = key.substring(key.indexOf("_") + 1);
					} catch (Exception e) {
						throw new RuntimeException("未知的判断条件：" + key, e);
					}
				}
				filters.add(new QueryFilter(fieldName, op, value));
			});
			return this;
		}
	}
}
